from hashlib import md5

from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash

from app import db, login
from datetime import datetime

@login.user_loader
def load_user(id):
    return User.query.get(int(id))

# 关注表设计  被关注者-粉丝
followers = db.Table(
	'followers',
	db.Column('follower_id', db.Integer, db.ForeignKey('user.id')),
	db.Column('followed_id', db.Integer, db.ForeignKey('user.id'))
	)
class User(UserMixin,db.Model):
	id = db.Column(db.Integer, primary_key=True)
	username = db.Column(db.String(64), index=True, unique=True)
	email = db.Column(db.String(120), index=True, unique=True)
	password_hash = db.Column(db.String(256))
	posts = db.relationship('Post', backref='author', lazy='dynamic')
	about_me = db.Column(db.String(140))
	last_seen = db.Column(db.DateTime, default=datetime.utcnow)
	# 关注
	# 定义一个双向关系，使得User类的实例可以相互关注
	followed = db.relationship(
		'User',  # 关联的模型是User类，表示用户之间的关系
		secondary=followers,  # 使用followers表作为中间表，这个表记录了所有的关注关系
		primaryjoin=(followers.c.follower_id == id),  # 定义用户（主表）的id和followers表中的follower_id的关联条件，即“我”关注了谁
		secondaryjoin=(followers.c.followed_id == id),  # 定义followers表中的followed_id和用户（副表）的id的关联条件，即“谁”关注了我
		backref=db.backref('followers', lazy='dynamic'),  # 在User类中添加一个名为followers的反向引用，可以通过user.followers查询所有关注了这个用户的人
		lazy='dynamic'  # 使用动态查询模式，只有在实际需要时才会从数据库中加载相关的数据
	)

	def follow(self, user):
		if not self.is_following(user):
			self.followed.append(user)

	def unfollow(self, user):
		if self.is_following(user):
			self.followed.remove(user)

	def is_following(self, user):
		return self.followed.filter(followers.c.followed_id == user.id).count() > 0

	def followers_count(self):
		return self.followers.count()

	def followed_count(self):
		return self.followed.count()

	# def followed_posts(self):
		"""
	 获取当前用户关注的帖子列表。

	 该方法通过查询数据库，获取当前用户（self）关注的所有用户的帖子。
	 查询首先连接到followers表和Post表，基于followed_id和user_id的关联进行。
	 接着，过滤出关注者的帖子，即follower_id等于当前用户的id。
	 最后，按帖子的创建时间降序排序返回结果。

	 返回:
	 一个查询结果对象，包含当前用户关注的用户发布的所有帖子，按时间降序排列。
	 """

	def followed_posts(self):
		followed = Post.query.join(followers, (followers.c.followed_id == Post.user_id)).filter(
			followers.c.follower_id == self.id)
		own = Post.query.filter_by(user_id=self.id)
		return followed.union(own).order_by(Post.timestamp.desc())

	def set_password(self, password):
		self.password_hash = generate_password_hash(password)

	def check_password(self, password):
		return check_password_hash(self.password_hash, password)

	def avatar(self, size):
		digest = md5(self.email.lower().encode('utf-8')).hexdigest()
		return 'https://www.gravatar.com/avatar/{}?d=identicon&s={}'.format(
			digest, size)

	def __repr__(self):
		return '<User {}>'.format(self.username)

class Post(db.Model):
	id = db.Column(db.Integer, primary_key=True)
	body = db.Column(db.String(140))
	timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
	user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

	def __repr__(self):
		return '<Post {}'.format(self.body)

